﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Styx;
using Styx.WoWInternals.WoWObjects;
using Styx.CommonBot.Routines;
using System.Diagnostics;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;
using Styx.CommonBot;
using Styx.WoWInternals;

namespace XS
{
    class XS_Hunter : CombatRoutine
    {
        /* SETTINGS! someone build a gui for them. I won't! */
        #region SETTINGS
        /// <summary>
        /// set true for questing, farming, grinding, bgbuddy, dungeonbuddy and all the unattended bots, set false for lazyraider, tyrael, raidbot, combatbot
        /// i'll let the CC decide what mode it is, later on. not yet though. to do list, added! (thats a lie)
        /// </summary>
        public static bool varUseWithUnattendedBot = false; //not yet coded

        /// <summary>
        /// set the number on >= X Adds the AoE rotation gets invoked
        /// </summary>
        public static int varAdds = 4;

        /// <summary>
        /// we rrr a hunter, we has pet. heal it? recommendation: yes!
        /// </summary>
        //public static int varPetNumber = 4; no yet
        public static bool varMendPet = true;
        public static int varMendPetHealtPercent = 70;

        /// <summary>
        /// there are some errors with detecting which trinkets r usable and which r not, so set trinket1 (slot 13) to true fo use, and trinket2 (14) yay.
        /// </summary>
        public static bool varTrinket1 = false;     //set true/false to use First Trinket (Trinkets will be used on CD, not only Boss!
        public static bool varTrinket2 = false;    //set true/false to use Second Trinket (Trinkets will be used on CD, not only Boss!
        #endregion

        #region NOT SETTINGS
        /* this one really is important for the sake of mankind */
        #region !IMPORTANT! INCLUDE THIS IN EVERY MAIN CLASSFILE! !IMPORTANT!
        public override WoWClass Class { get { return WoWClass.Hunter; } }
        public override string Name { get { return "XS " + XSCommon.version; } }
        private static LocalPlayer Me { get { return XSCommon.Me; } }
        private delegate WoWUnit UnitSelection(object unit);
        public override bool WantButton
        {
            get
            {
                return XSCommon.WantButton;
            }
        }
        public override void OnButtonPress()
        {
            XSCommon.OnButtonPress();
        }
        public override void Initialize()
        {
            XSCommon.Initialize(Name, Me);
        }
        public override void Pulse()
        {
            XSCommon.Pulse();
        }
        #endregion


        /* decidated functions for helping our hunter to do its stuff */
        private Stopwatch ReviveTimer = new Stopwatch();
        private Composite RevivePet(CanRunDecoratorDelegate cond)
        {
            return RevivePet(ret => Me, cond);
        }
        private Composite RevivePet(UnitSelection onUnit, CanRunDecoratorDelegate cond)
        {
            return (
                new Decorator(delegate(object a)
                {
                    if (!cond(a))
                        return false;
                    if (!XSCommon.CanCast("Revive Pet", onUnit(a)))
                        return false;
                    return onUnit(a) != null;
                },
                    new Sequence(
                        new Action(a => ReviveTimer.Start()),
                        new Action(a => XSCommon.write("[Revive Pet] {1}", XSCommon.safeName(onUnit(a)))),
                        new Action(a => SpellManager.Cast("Revive Pet", onUnit(a))))));
        }
        private Composite CallPet(string spellName, CanRunDecoratorDelegate cond)
        {
            return CallPet(spellName, ret => Me, cond);
        }
        private Composite CallPet(string spellName, UnitSelection onUnit, CanRunDecoratorDelegate cond)
        {
            return (
                new Decorator(delegate(object a)
                {
                    if (!cond(a))
                        return false;
                    if (!XSCommon.CanCast(spellName, onUnit(a)))
                        return false;
                    return onUnit(a) != null;
                },
                    new Sequence(
                        new Action(a => ReviveTimer.Reset()),
                        new Action(a => XSCommon.write("[Calling] {1}", XSCommon.safeName(onUnit(a)))),
                        new Action(a => SpellManager.Cast(spellName, onUnit(a))))));
        }


        /* Now that we've taken care of senseless fuck, lets dive into deciding what to do. */
        public override Composite CombatBehavior
        {
            get
            {
                return (
                    new PrioritySelector(
                        /* choo choo */
                        new Decorator(ret => SpellManager.GlobalCooldownLeft.Milliseconds > 200 || Me.Mounted || Me.IsChanneling || Me.IsCasting, //we should add a "if spellcast.timeleft < 200ms then GO FOR IT, for speedup porposes eh?
                            new Action(
                                delegate
                                {
                                    return RunStatus.Failure;
                                }
                            )
                        ),
                        /* this is where we take care of our pet & make it attack our target like a baws */
                        /*new PrioritySelector(ret => !Me.GotAlivePet,
                            RevivePet(ret => Me.Pet.IsDead),
                            CallPet("Call Pet "+ varPetNumber, ret => !Me.Pet.IsDead)
                        ),*/
                        new PrioritySelector(ret => Me.GotAlivePet,
                            new Decorator(ret => XS_Hunter.varMendPet && Me.Pet.HealthPercent <= XS_Hunter.varMendPetHealtPercent && XSCommon.MyAuraTime("Mend Pet", Me.Pet) < 1,
                                XSCommon.CastSelfSpell("Mend Pet", ret => true)
                            ),
                            new Decorator(ret => Me.GotTarget && Me.Pet.CurrentTargetGuid != Me.CurrentTargetGuid,
                                new Action(
                                    delegate
                                    {
                                        Lua.DoString("PetAttack()");
                                        XSCommon.write("[Pet] Attack my Target");
                                        return RunStatus.Failure;
                                    }
                                )
                            )
                        ),
                        /* everything fine, lets do something */
                        new Decorator(ret => XSCommon.TargetIsValid(),
                            new PrioritySelector(
                                new PrioritySelector(
                                    XS_Hunter_Survival.AoE(ret => XSCommon.AddCount() >= XS_Hunter.varAdds && !XSCommon.TargetIsPlayer()),
                                    XS_Hunter_Survival.Player(ret => XSCommon.TargetIsPlayer()),
                                    XS_Hunter_Survival.Boss(ret => XSCommon.TargetIsBoss()),
                                    XS_Hunter_Survival.Normal(ret => !XSCommon.TargetIsPlayer() && !XSCommon.TargetIsBoss() && XSCommon.AddCount() < XS_Hunter.varAdds)
                                ),
                                new PrioritySelector(
                                    XS_Hunter_Marksmanship.AoE(ret => XSCommon.AddCount() >= XS_Hunter.varAdds && !XSCommon.TargetIsPlayer()),
                                    XS_Hunter_Marksmanship.Player(ret => XSCommon.TargetIsPlayer()),
                                    XS_Hunter_Marksmanship.Boss(ret => XSCommon.TargetIsBoss()),
                                    XS_Hunter_Marksmanship.Normal(ret => !XSCommon.TargetIsPlayer() && !XSCommon.TargetIsBoss() && XSCommon.AddCount() < XS_Hunter.varAdds)
                                ),
                                new PrioritySelector(
                                    XS_Hunter_BeastMastery.AoE(ret => XSCommon.AddCount() >= XS_Hunter.varAdds && !XSCommon.TargetIsPlayer()),
                                    XS_Hunter_BeastMastery.Player(ret => XSCommon.TargetIsPlayer()),
                                    XS_Hunter_BeastMastery.Boss(ret => XSCommon.TargetIsBoss()),
                                    XS_Hunter_BeastMastery.Normal(ret => !XSCommon.TargetIsPlayer() && !XSCommon.TargetIsBoss() && XSCommon.AddCount() < XS_Hunter.varAdds)
                                )/*,
                                
                                new PrioritySelector(
                                    XS_Hunter_NoSpec.AoE(ret => XSCommon.AddCount() >= XS_Hunter.varAdds && !XSCommon.TargetIsPlayer()),
                                    XS_Hunter_NoSpec.Player(ret => XSCommon.TargetIsPlayer()),
                                    XS_Hunter_NoSpec.Boss(ret => XSCommon.TargetIsBoss()),
                                    XS_Hunter_NoSpec.Normal(ret => !XSCommon.TargetIsPlayer() && !XSCommon.TargetIsBoss() && XSCommon.AddCount() < XS_Hunter.varAdds)
                                )*/
                            )
                        )
                    )
                );
            }
        }
        /*private Composite Rotation(CanRunDecoratorDelegate cond, string switcher)
        {
            switch (Me.Specialization)
            {
                case WoWSpec.HunterSurvival:
                    switch (switcher)
                    {
                        case "Player":
                            return XS_Hunter_Survival.Player();
                        case "Boss":
                            return XS_Hunter_Survival.Boss();
                        case "AoE":
                            return XS_Hunter_Survival.AoE();
                        case "Normal":
                            return XS_Hunter_Survival.Normal();
                        default:
                            return XS_Hunter_Survival.Normal();
                    }
                case WoWSpec.HunterMarksmanship:
                    switch (switcher)
                    {
                        case "Player":
                            return XS_Hunter_Marksmanship.Player();
                        case "Boss":
                            return XS_Hunter_Marksmanship.Boss();
                        case "AoE":
                            return XS_Hunter_Marksmanship.AoE();
                        case "Normal":
                            return XS_Hunter_Marksmanship.Normal();
                        default:
                            return XS_Hunter_Survival.Normal();
                    }
                case WoWSpec.HunterBeastMastery:
                    switch (switcher)
                    {
                        case "Player":
                            return XS_Hunter_BeastMastery.Player();
                        case "Boss":
                            return XS_Hunter_BeastMastery.Boss();
                        case "AoE":
                            return XS_Hunter_BeastMastery.AoE();
                        case "Normal":
                            return XS_Hunter_BeastMastery.Normal();
                        default:
                            return XS_Hunter_Survival.Normal();
                    }
                default:
                    switch (switcher)
                    {
                        case "Player":
                            return XS_Hunter_NoSpec.Player();
                        case "Boss":
                            return XS_Hunter_NoSpec.Boss();
                        case "AoE":
                            return XS_Hunter_NoSpec.AoE();
                        case "Normal":
                            return XS_Hunter_NoSpec.Normal();
                        default:
                            return XS_Hunter_Survival.Normal();
                    }
            }
        }*/
        #endregion
    }
}
